package com.ccteam.fluidmusic.ui.local.artist

import android.net.Uri
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaMetadataCompat
import androidx.lifecycle.*
import com.ccteam.fluidmusic.ui.PARENT_ID_KEY
import com.ccteam.fluidmusic.fluidmusic.common.MusicServiceConnectionFlow
import com.ccteam.fluidmusic.fluidmusic.media.extensions.METADATA_KEY_ALBUM_ID
import com.ccteam.fluidmusic.fluidmusic.media.extensions.METADATA_KEY_ARTIST_ID
import com.ccteam.fluidmusic.fluidmusic.media.extensions.id
import com.ccteam.fluidmusic.utils.cancelIfActive
import com.ccteam.model.Resource
import com.ccteam.shared.result.artist.ArtistInfoData
import com.ccteam.shared.result.music.DefaultMusicItem
import com.ccteam.shared.utils.NO_PLAYING
import com.ccteam.shared.utils.PLAYING
import com.ccteam.shared.utils.getPlaybackStatus
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/2/9
 *
 * 本地歌手详情页歌曲内容ViewModel
 **/
@HiltViewModel
class LocalArtistDetailMusicViewModel @Inject constructor(
    private val musicServiceConnectionFlow: MusicServiceConnectionFlow,
    savedStateHandle: SavedStateHandle
): ViewModel() {

    private val _musicItems = MutableLiveData<Resource<List<DefaultMusicItem>>>(Resource.Loading(null))
    val musicItems: LiveData<Resource<List<DefaultMusicItem>>> = _musicItems

    private var parentId: String? = null

    /**
     * 订阅回调
     * 收到具体专辑内容的信息后进入协程进行处理
     */
    private val subscriptionCallback = object : MediaBrowserCompat.SubscriptionCallback() {
        override fun onChildrenLoaded(parentId: String, children: List<MediaBrowserCompat.MediaItem>) {
            viewModelScope.launch {
                handleArtistMusicItem(children)
            }
        }
    }

    private var metadataChangeJob: Job? = null

    init {
        savedStateHandle.get<String>(PARENT_ID_KEY)?.let {
            this.parentId = it
            musicServiceConnectionFlow.subscribe(it, subscriptionCallback)

            metadataChangeJob = viewModelScope.launch(Dispatchers.Default) {
                musicServiceConnectionFlow.nowPlaying.collectLatest { metadata ->
                    _musicItems.postValue(handleMusicMediaDataChanged(metadata))
                }
            }
        }
    }

    private suspend fun handleArtistMusicItem(children:List<MediaBrowserCompat.MediaItem>){
        withContext(Dispatchers.Default){
            val itemsList = children.map { child ->
                val artistInfo = child.description.extras?.getString(METADATA_KEY_ARTIST_ID)?.let {
                    listOf(ArtistInfoData(it,child.description.subtitle.toString()))
                } ?: emptyList()
                DefaultMusicItem(
                    child.mediaId!!,
                    child.description.title.toString(),
                    child.description.subtitle.toString(),
                    artistInfo,
                    child.description.extras?.getString(METADATA_KEY_ALBUM_ID) ?: "-1",
                    child.description.iconUri.toString(),
                    null,
                    true,
                    musicServiceConnectionFlow.nowPlaying.value.getPlaybackStatus(child.mediaId!!),
                    child.description.mediaUri ?: Uri.EMPTY
                )
            }
            _musicItems.postValue(Resource.Success(itemsList))
        }
    }

    /**
     * 如果当前播放内容发生变化，则处理MusicMediaData歌曲项的内容
     * 把正在播放的项的内容更改
     */
    private fun handleMusicMediaDataChanged(
        mediaMetadata: MediaMetadataCompat
    ): Resource<List<DefaultMusicItem>>{
        val newMediaData = _musicItems.value?.data?.map {
            val useResId = if (it.mediaId == mediaMetadata.id) PLAYING else NO_PLAYING
            it.copy(playbackRes = useResId)
        } ?: emptyList()
        return Resource.Success(newMediaData)
    }

    override fun onCleared() {
        super.onCleared()

        metadataChangeJob.cancelIfActive()

        parentId?.let {
            musicServiceConnectionFlow.unsubscribe(it,subscriptionCallback)
        }
    }


}